import { FYE } from '../../Global/FYE';
import FYSDKMgr from '../../SDK/FYSDKMgr';
import FYUtility from '../../Util/FYUtility';
import FYLog from '../FYLog';
import LocalStorageMgr from '../LocalStorageMgr';
import FYResMgr from '../Res/FYResMgr';

export default class FYAudioMgr {
    public static readonly Instance: FYAudioMgr = new FYAudioMgr();
    private constructor() { }

    //--------------------------------------------------------------------------------
    //#region ------------------------ 同步加载资源模式 ------------------------
    //--------------------------------------------------------------------------------

    /** 声音音量 */
    private _soundVolume: number = null;
    public get SoundVolume(): number {
        if (this._soundVolume == null)
            this._soundVolume = LocalStorageMgr.GetNumber('SoundVolume', 1)
        return this._soundVolume;
    }
    public set SoundVolume(value: number) {
        this._soundVolume = value
        LocalStorageMgr.SetNumber('SoundVolume', this._soundVolume)
        FYAudioMgr.Instance.SetSoundVolume(value);
    }

    /** 音乐音量 */
    private musicVolume: number = null;
    public get MusicVolume(): number {
        if (this.musicVolume == null)
            this.musicVolume = LocalStorageMgr.GetNumber('MusicVolume', 1)
        return this.musicVolume;
    }
    public set MusicVolume(value: number) {
        this.musicVolume = value
        LocalStorageMgr.SetNumber('MusicVolume', this.musicVolume)
        FYAudioMgr.Instance.SetMusicVolume(value);
    }

    private EffectSoundList: Map<string, Array<number>>;

    /** 初始化 */
    public Init() {
        this.EffectSoundList = new Map<string, Array<number>>();
        cc.audioEngine.setMusicVolume(this.MusicVolume)
        cc.audioEngine.setEffectsVolume(this.SoundVolume)
    }

    /**
     * 播放音乐
     * @param name 音乐名
     * @param isLoop 是否循环
     */
    public async PlayMusic(name: string, isLoop: boolean = true) {
        if (FYUtility.IsNullOrEmpty(name)) {
            return;
        }
        try {
            let clip: cc.AudioClip = await FYResMgr.Instance.LoadRes(name, cc.AudioClip);
            let MusicId = cc.audioEngine.playMusic(clip, isLoop);
        } catch (error) {
            console.error(error);
        }
    }

    /**
     * 关闭音乐
     */
    public StopMusic() {
        cc.audioEngine.stopMusic();
    }

    /**
     * 播放音效
     * @param name 音效名
     */
    public async PlaySound(name: string) {
        if (FYUtility.IsNullOrEmpty(name)) {
            return;
        }
        if (this.SoundVolume <= 0.01) {
            return;
        }

        // 获取播放分组
        let SoundList = this.EffectSoundList.get(name);
        if (!SoundList) {
            SoundList = new Array<number>();
            this.EffectSoundList.set(name, SoundList);
        }

        // 每个声音播放最小间隔
        let now = new Date().getTime();
        if (SoundList.length > 0) {
            if (now - SoundList[0] < 150)
                return;
        }

        // 清除播放时间大于1000毫秒的声音
        while (SoundList.length > 0) {
            if (now - SoundList[0] > 500)
                SoundList.shift();
            else
                break;
        }

        // 同时存在声音数
        if (SoundList.length > 7) {
            return;
        }

        SoundList.push(now);
        try {
            let clip: cc.AudioClip = await FYResMgr.Instance.LoadRes(name, cc.AudioClip);
            cc.audioEngine.playEffect(clip, false);
        } catch (error) {
            console.error(error);
        }

    }

    /**
     * 通过声音Id关闭音效
     * @param audioId 音效名
     */
    public StopSound(audioId: number) {
        if (audioId < 0) {
            return;
        }
        cc.audioEngine.stopEffect(audioId)
    }

    /**
     * 关闭所有循环的音频
     */
    public StopAllSounds() {
        cc.audioEngine.stopAllEffects()
    }

    /**
     * 设置音效大小
     * @param value 
     */
    public SetSoundVolume(value: number) {
        cc.audioEngine.setEffectsVolume(value)
    }

    /**
     * 设置音乐大小
     * @param value 
     */
    public SetMusicVolume(value: number) {
        cc.audioEngine.setMusicVolume(value)
    }

    //#endregion

    //--------------------------------------------------------------------------------
    //#region ------------------------ 先加载所有资源再使用模式 ------------------------
    //--------------------------------------------------------------------------------

    private arrayMusic = {};
    private arraySound = {};
    private _bMute = false;
    private _curType: FYE.MusicType = FYE.MusicType.music_bg;

    public getSound(type: FYE.SoundType) {
        if (type in this.arraySound) {
            return this.arraySound[type];
        } else {
            this.arraySound[type] = FYSDKMgr.Instance.getSound(type);

            return this.arraySound[type];
        }
    }

    public getMusic(type: FYE.MusicType) {
        if (type in this.arrayMusic) {
            return this.arrayMusic[type];
        } else {
            this.arrayMusic[type] = FYSDKMgr.Instance.getMusic(type);

            return this.arrayMusic[type];
        }
    }

    public playSound(type: FYE.SoundType) {

        if (this._bMute) {
            return;
        }

        FYSDKMgr.Instance.playSound(this.getSound(type));
    }

    public playMusic(type: FYE.MusicType) {
        if (this._bMute) {
            return;
        }

        FYLog.log("---> 播放背景音乐 <---");

        FYSDKMgr.Instance.playMusic(this.getMusic(type));

        this._curType = type;
    }

    public resumePre() {
        if (this._bMute) {
            return;
        }
        // this.stopAllMusic();
        // this.destroyMusic();
        this.playMusic(this._curType);
    }

    public pauseMusic() {
        this.getMusic(this._curType).pause();
    }

    public stopAllMusic() {
        for (let i in this.arrayMusic) {
            FYSDKMgr.Instance.stopMusic(this.getMusic(<FYE.MusicType>i));
        }
    }

    public stopAllSound() {
        for (let i in this.arraySound) {
            FYSDKMgr.Instance.stopSound(this.getSound(<FYE.SoundType>i));
        }
    }

    public destroyAll() {
        for (let i in this.arrayMusic) {
            this.arrayMusic[i].destroy();
        }

        for (let i in this.arraySound) {
            this.arraySound[i].destroy();
        }

        this.arrayMusic = {};
        this.arraySound = {};
    }

    public destroyMusic() {
        for (let i in this.arrayMusic) {
            this.arrayMusic[i].destroy();
        }
    }

    public destroySound() {
        for (let i in this.arraySound) {
            this.arraySound[i].destroy();
        }
    }

    /**
     * 静音
     * @param bMute 是否静音
     */
    public Mute(bMute) {
        this._bMute = bMute;
        if (this._bMute) {
            // this.destroyAll();
            this.stopAllMusic();
            this.stopAllSound();
            console.log("---> 静音")
        } else {
            this.playMusic(this._curType);
            console.log("---> 恢复声音")
        }
    }

    //#endregion
}
